Hace poco he estado usando [jupyter](https://jupyter.org/) y el entorno python para ciencia de datos. A medida que me iba acostumbrando, me di cuenta de que escribir código usando un navegador web no es de lo más cómodo, en especial teniendo en cuenta que me gusta usar mucho el editor [emacs](https://www.gnu.org/software/emacs/).

En este post mostraré una forma de escribir los notebooks de jupyter y ver los resultados directamente en emacs usando la extensión [emacs-jupyter](https://github.com/dzop/emacs-jupyter).

## Requisitos

Básicamente tener una instalación de jupyter y de emacs, para mi caso esto es lo que tengo.

  - [Anaconda 3](https://www.anaconda.com/): Como entorno python para ciencia de datos, incluye jupyter.
  - [Emacs 26](https://www.gnu.org/software/emacs/): La versión 26 y posiblemente posteriores facilita la instalación.

Estoy usando Trisquel 8 una distribución GNU/Linux basada en ubuntu 16.

### Instalación

Asumiendo que se tiene instalado jupyter y el entorno python que viene con anaconda 3, es importante tener instalado emacs 26.

#### Instalando emacs 26

Si tienes ya emacs 26 podrías saltarte este paso, en mi caso, la instalación de emacs mediante `apt` era para una versión anterior a la 26 de emacs por lo que tuve que optar por la instalación manual construyendo desde el código fuente que describiré a continuación.

1. Descargar la última versión 26 de emacs, que se puede hacer desde el [ftp](http://gnu.c3sl.ufpr.br/ftp/emacs) o directamente [http://gnu.c3sl.ufpr.br/ftp/emacs/emacs-26.3.tar.gz](http://gnu.c3sl.ufpr.br/ftp/emacs/emacs-26.3.tar.gz).

2. Extraer el contenido con `tar xvf emacs-26.3.tar.gz`.

3. Una vez extraído, hay que seguir las instrucciones del archivo `INSTALL`, en mi caso hice lo siguiente.

Comprobar dependencias

    :::bash
    ./configure


Que seguramente mostrará mensajes con librerías faltantes, en mi caso tuve que instalar `libxmp-dev libtiff-dev`. 

4. Construir el binario. 

Una vez ./configure salga sin retornar errores:

    :::bash
    make
    # luego de terminado, para instalar en el sistema de forma global
    sudo make install

### Extensión emacs-jupyter

[emacs-jupyter](https://github.com/dzop/emacs-jupyter) es una extensión que permite conectarse a los *kernels* de jupyter y usar emacs como "cliente". La instalación es sencilla si se tiene instalado emacs 26 y solo bastará con introducir dentro de emacs: `M-x package-refresh-contents RET` luego `M-x package-install RET jupyter RET`.

Esta extensión usa la extensión [ein](https://github.com/millejoh/emacs-ipython-notebook) como cliente jupyter, si no esta instalada se puede hacer con `M-x package-install ein RET`.

### Probando la instalación

Ahora podemos verificar haciendo lo siguiente en emacs:

1. Abrir un archivo de notebook jupyter (extensión `.ipynb`). 
2. Ejecutar `ein:run`.

Si todo va bien, deberíamos poder ver los archivos y poder editarlos desde emacs.

![emacs-jupyter-1](/static/imgs/posts/emacs-jupyter-1.jpg)

`ein` cuenta con un cómodo menú y muchas opciones para trabajar con el archivo en jupyter.

![emacs-jupyter-2](/static/imgs/posts/emacs-jupyter-2.jpg)

Pero seguramente no funcionará si intentamos ejecutar el código de la celda desde emacs (con `C-c C-c`).

#### Configurando jupyter para conectarse usando una contraseña

Jupyter permite conectarse a su servidor y ejecutar código python, pero tiene la medida de seguridad de requerir autenticación e iniciar sesión para usar los *kernels*. Para conectar emacs al *kernel* de jupyter, este necesita autenticarse.

Por defecto jupyter crea un token para cada sesión y tendríamos que de alguna forma obtener los tokens de las sesiones de jupyter y hacer que emacs los use para conectarse. Pero esto se puede automatizar y ahorrarnos la necesidad de buscar tokens cada que iniciemos una instancia de jupyter.

La [documentación de jupyter](https://jupyter-notebook.readthedocs.io/en/stable/public_server.html) indica una forma de definir un password para que los programas clientes se conecten a los *kernels* de jupyter, yo seguí estos pasos:

Abrir una terminal y activar el entorno virtual de python que usa anaconda 3.

    :::bash
    source /directorio-donde-se-descargo-anaconda3/bin/activate
    # Una vez se active el entorno generamos un archivo de configuracion para jupyter
    jupyter notebook --generate-config
    # Que devolveria algo asi
    # Writing default config to: /home/usuario/.jupyter/jupyter_notebook_config.py

Ahora editaremos generaremos una clave que luego copiaremos al archivo `jupyter_notebook_config.py` recién generado.


    :::bash
    ipython
    # En la consola ipython
    In [1]: from notebook.auth import passwd
    In [2]: passwd() # esto nos pedirá un password que debemos introducir
    Enter password:
    Verify password:
    Out[2]: 'sha1:67c9e60bb8b6:9ffede08258942e4b2e042eae97d721089e11aed'

Copiamos el resultado de `passwd()` en este caso `sha1:67c9e60bb8b6:9ffede08258942e4b2e042eae97d721089e11aed` y lo copiamos en el archivo `/home/usuario/.jupyter/jupyter_notebook_config.py` descomentando en la linea y reemplazando por el digesto que generó passwd():

    :::python
    c.NotebookApp.password = 'sha1:67c9e60bb8b6:9ffede08258942e4b2e042eae97d721089e11aed'

Una vez hecho esto, guardamos el archivo e iniciamos un jupyter notebook. Por ejemplo desde anaconda-navigator se abrirá el cliente jupyter por defecto que es una pestaña en nuestro navegador y debería pedir que introduzcamos un password para ingersar y ahí introduciremos el password que definimos.

![emacs-jupyter-3](/static/imgs/posts/emacs-jupyter-3.jpg)

Si funciona, ya podemos autenticarnos desde emacs para lo que ejecutamos `ein-login` y este nos pedirá que introduzcamos una URL y luego de eso el password.

![emacs-jupyter-4](/static/imgs/posts/emacs-jupyter-4.jpg)

Una vez introducimos el password que definimos, emacs se conectará al kernel de jupyter y mostrará un navegador de archivos donde podremos navegar y escoger el archivo que queremos editar.

![emacs-jupyter-5](/static/imgs/posts/emacs-jupyter-5.jpg)

El archivo se abrirá (quizá tarde un poco), para terminar de probar ejecutamos cualquier celda (`C-c C-c`) y se debería ejecutar y ver el resultado en emacs :D

![emacs-jupyter-6](/static/imgs/posts/emacs-jupyter-6.jpg)

### Comentarios finales

Gracias al diseño de jupyter que permite a programas clientes conectarse y usar el *backend* de jupyter se puede hacer que emacs sea también otro cliente. Esto abrió la posiblidad de que se escriban las extensiones [emacs-jupyter](https://github.com/dzop/emacs-jupyter) y [ein](https://github.com/millejoh/emacs-ipython-notebook) que funcionan muy bien.

La ventajas de usar emacs como cliente de jupyter para mi son:

- Te libras de la edición en navegador web.
- El autocompletado es más rápido.
- Usas emacs.

Espero te haya servido.
